#include "BlockQueue.hpp"
#include "Task.hpp"
#include <iostream>
#include <pthread.h>
#include <unistd.h>

// void *consumer(void *args)
// {
//     BlockQueue<task_t> *bq = static_cast<BlockQueue<task_t> *>(args);

//     while (true)
//     {
//         sleep(3);
//         // 1. 消费任务
//         task_t t = bq->Pop();

//         // 2. 处理任务 -- 处理任务的时候，这个任务，已经被拿到线程的上下文中了,不属于队列了
//         t();
//     }
// }

// void *productor(void *args)
// {
//     BlockQueue<task_t> *bq = static_cast<BlockQueue<task_t> *>(args);
//     while (true)
//     {
//         // 1. 获得任务
//         //std::cout << "生产了一个任务: " << x << "+" << y << "=?" << std::endl;
//         std::cout << "生产了一个任务: " << std::endl;

//         // 2. 生产任务
//         bq->Equeue(Download);
//     }
// }

// int main()
// {
//     // 扩展认识: 阻塞队列: 可以放任务吗？
//     // 申请阻塞队列
//     BlockQueue<task_t> *bq = new BlockQueue<task_t>();

//     // 构建生产和消费者
//     pthread_t c[1], p[1];

//     pthread_create(c, nullptr, consumer, bq);
//     // pthread_create(c+1, nullptr, consumer, bq);
//     pthread_create(p, nullptr, productor, bq);
//     // pthread_create(p+1, nullptr, productor, bq);
//     // pthread_create(p+2, nullptr, productor, bq);

//     pthread_join(c[0], nullptr);
//     // pthread_join(c[1], nullptr);
//     pthread_join(p[0], nullptr);
//     // pthread_join(p[1], nullptr);
//     // pthread_join(p[2], nullptr);

//     return 0;
// }











#include <iostream>
#include <vector>
#include <string>
#include <unistd.h>
#include <pthread.h>
const int NUM = 5;
int cnt = 0;

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

void *thread_func(void *args)
{
    std::string s = static_cast<const char *>(args);
    while (true)
    {
        pthread_mutex_lock(&lock);
        // 注意，这里的等待是有条件的等，而测试代码没有条件限制
        pthread_cond_wait(&cond, &lock);
        std::cout << s << ", cnt: " << cnt << std::endl;
        cnt++;
        pthread_mutex_unlock(&lock);
    }
    return nullptr;
}

int main()
{
    std::vector<pthread_t> tids;
    for (int i = 0; i < NUM; i++)
    {
        pthread_t tid;
        char *name = new char[64];
        snprintf(name, 64, "thread-%d", i);
        pthread_create(&tid, nullptr, thread_func, name);
        tids.push_back(tid);
    }
    sleep(2);

    while (1)
    {
        // std::cout << "wake up all thread" << std::endl;
        // pthread_cond_broadcast(&cond);
        std::cout << "wake up a thread" << std::endl;
        pthread_cond_signal(&cond);
        sleep(1);
    }

    for (auto tid : tids)
        pthread_join(tid, nullptr);

    return 0;
}

// wake up a thread
// thread-0, cnt: 0
// wake up a thread
// thread-1, cnt: 1
// wake up a thread
// thread-2, cnt: 2
// wake up a thread
// thread-3, cnt: 3
// wake up a thread
// thread-4, cnt: 4